#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


#define NUM_OF_TASKS 3
#define MAX_TASK_QUEUE 11

/*
 * 线程互斥
 */

char tasklist[MAX_TASK_QUEUE] = "ABCDEFGHIJ";
int head = 0;
int tail = 0;

int quit = 0;

pthread_mutex_t g_task_lock;
pthread_cond_t g_task_cv;

void *coder(void *notused) {
    pthread_t tid = pthread_self();

    while (!quit) {

        pthread_mutex_lock(&g_task_lock);
        while (tail == head) {
            if (quit) {
                pthread_mutex_unlock(&g_task_lock);
                pthread_exit((void *) 0);
            }
            printf("No task now! Thread %u is waiting!\n", (unsigned int) tid);
            pthread_cond_wait(&g_task_cv, &g_task_lock);
            printf("Have task now! Thread %u is grabing the task !\n", (unsigned int) tid);
        }
        char task = tasklist[head++];
        pthread_mutex_unlock(&g_task_lock);
        printf("Thread %u has a task %c now!\n", (unsigned int) tid, task);
        sleep(5);
        printf("Thread %u finish the task %c!\n", (unsigned int) tid, task);
    }

    pthread_exit((void *) 0);
}

int main1(int argc, char *argv[]) {
    pthread_t threads[NUM_OF_TASKS];
    int rc;
    int t;

    pthread_mutex_init(&g_task_lock, NULL);
    pthread_cond_init(&g_task_cv, NULL);

    for (t = 0; t < NUM_OF_TASKS; t++) {
        rc = pthread_create(&threads[t], NULL, coder, NULL);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    sleep(5);

    for (t = 1; t <= 4; t++) {
        pthread_mutex_lock(&g_task_lock);
        tail += t;
        printf("I am Boss, I assigned %d tasks, I notify all coders!\n", t);
        pthread_cond_broadcast(&g_task_cv);
        pthread_mutex_unlock(&g_task_lock);
        sleep(20);
    }

    pthread_mutex_lock(&g_task_lock);
    quit = 1;
    pthread_cond_broadcast(&g_task_cv);
    pthread_mutex_unlock(&g_task_lock);

    pthread_mutex_destroy(&g_task_lock);
    pthread_cond_destroy(&g_task_cv);
    pthread_exit(NULL);
}